local blaze = require "blaze"
local app = require "app"
local gamelib = require "club.threecard.gamelib"
local game = require "club.threecard.jacksorbetter"
local consts = game.util.consts

local log = blaze.logging.get("GameUI")

local M = game.ui.activity()

local function update_selectable_cards(self, state)
    if state.is_picking_phase then
        self.poker_container.config.ope_valid = true
    else
        self.poker_container.config.ope_valid = false
        local hand = self.poker_container.hand
        for index, poker in ipairs(hand) do
            poker:forbid()
        end
    end
end

local function update_phase_state(self, state)
    self.double_btn.gameObject:SetActive(state.phase == consts.PHASE_WIN)
    self.phase_txt.text = state.phase_tip
end

M.store_watchers = {
    ingame = {
        ["$"] = function(self, store, state, args)
            self.poker_container:mopai(state.cards)
            update_selectable_cards(self, state)
            update_phase_state(self, state)
        end,

        ["游戏开始"] = function(self, store, state, args)
            self.poker_container:mopai(state.cards)
            self:tip_hand(state.rank_class)
        end,

        ["开局发牌"] = function(self, store, state, args)
            local hand = self.poker_container.hand
            local left_count = #hand
            for index, poker in ipairs(hand) do
                poker:forbid2(false)
                poker:gray(false)
                poker:unselect()
                local value = state.cards[index]
                local poker_data = self.poker_container.config.poker_data_class.new(value)
                poker:flip(poker_data, function()
                    left_count = left_count - 1
                    if left_count == 0 then
                        self:tip_hand(state.rank_class)
                    end
                end)
            end
        end,

        ["结算亮牌"] = function(self, store, state, args)
            local hand = self.poker_container.hand
            local left_count = 0
            for _, poker in ipairs(hand) do
                poker:forbid2(false)
                if poker.selected then
                    left_count = left_count + 1
                end
            end

            if left_count == 0 then
                if state.rank_class < game.util.consts.RANK_JACKS_PAIR then
                    self:gray_hand(true)
                else
                    self:gray_hand(false)
                end
            end

            for index, poker in ipairs(hand) do
                if not poker.selected then
                    local value = state.cards[index]
                    local poker_data = self.poker_container.config.poker_data_class.new(value)
                    poker:flip(poker_data, function()
                        left_count = left_count - 1
                        if left_count <= 0 then
                            if state.rank_class < game.util.consts.RANK_JACKS_PAIR then
                                self:gray_hand(true)
                            else
                                self:gray_hand(false)
                            end
                        end
                    end)
                else
                    poker:unselect()
                end
            end
        end,

        ["赌博选牌"] = function(self, store, state, args)
            self.deal_btn.gameObject:SetActive(false)
            self:gray_hand(false)
            local hand = self.poker_container.hand
            for index, value in ipairs(state.cards) do
                if value > 0 then
                    local poker_data = self.poker_container.config.poker_data_class.new(value)
                    hand[index]:flip(poker_data)
                    hand[index]:forbid2(true)
                else
                    local poker = hand[index]
                    poker.click_handler = function(poker)
                        self:on_pick(poker)
                    end
                    poker:forbid2(false)
                end
            end
        end,

        ["赌博亮牌"] = function(self, store, state, args)
            self.deal_btn.gameObject:SetActive(true)
            self:gray_hand(false)
            local hand = self.poker_container.hand
            for index, poker in ipairs(hand) do
                poker:forbid2(false)
                if poker.selected then
                    poker:unselect()
                    local value = state.cards[index]
                    if value == nil then
                        log.error(string.format('错误的索引 index：%s cards：%s', index, game.dump(state.cards)))
                        log.error(state.cards)
                        for k, v in pairs(state.cards) do
                            log.error(string.format('key:%s value:%s', k, v))
                        end
                        return
                    end
                    local poker_data = self.poker_container.config.poker_data_class.new(value)
                    poker:flip(poker_data)
                end
            end
        end,

        ["最终结算"] = function(self, store, state, args)
            if args.result == consts.SETTLE_WIN then
                self.win_chip_anim:play(self.current_win_obj.transform, self.player_info_obj.transform)    
            end
        end,

        ["阶段变更"] = function(self, store, state, args)
            update_selectable_cards(self, state)
            update_phase_state(self, state)
        end,

        ["重置状态"] = function(self, store, state, args, init)
            self:clear()
        end
    }
}

function M:ctor()
    self.res = "club.threecard.jacksorbetter/ui/ingame.b:InGameUI"

    local config = game.require("poker_controller.poker_container_config")
    self.poker_container = game.pokerlib.core.poker_container.new(config)

    self.bet_viser = game.require("ui.ingame.BetViser").new()
    self.player_info = gamelib.require("widget.player_info").new()
    self.current_win = game.require("ui.ingame.CurrentWin").new()
    self.win_chip_anim = require("ui.Widget.chip_anim").new()
    self.server_time = require("ui.widgets.ServerTime").new()
    self.network_signal = require("ui.widgets.NetworkSignal").new()
end

function M:on_load()
    self:super("on_load")
end

function M:on_injected(bind)
    bind("button.click", self.exit_btn, self.on_exit_game)
    bind("shortcut.escape", self.exit_btn.gameObject, self.on_exit_game)
    bind("button.click", self.deal_btn, self.on_deal)
    bind("button.click", self.double_btn, self.on_double)
    bind("gameobject.element", self.player_info_obj, self.player_info)
    bind("gameobject.element", self.bet_operator_obj, self.bet_viser)
    bind("gameobject.element", self.poker_container_obj, self.poker_container)
    bind("gameobject.element", self.current_win_obj, self.current_win)
    bind("gameobject.element", self.server_time_obj, self.server_time)
    bind("gameobject.element", self.network_signal_obj, self.network_signal)

    app.utility.button_style.highlight(self.deal_btn)
    app.utility.button_style.highlight(self.double_btn)
end

function M:clear()
    self.poker_container:clear()
    self.poker_container:mopai(game.store.ingame.state.cards)
    self.double_btn.gameObject:SetActive(false)
end

local function do_double(self)
    local value = -1
    local poker_data = self.poker_container.config.poker_data_class.new(value)

    local hand = self.poker_container.hand
    local is_flip = false
    for _, poker in ipairs(hand) do 
        if poker.data.client_value ~= -1 then
            poker:flip(poker_data)
            is_flip = true
        end   
    end

    if is_flip then
        game.input.wait(0.6, "赌博翻牌动画")
    end

    game.store.ingame.double()
end

function M:on_double()
    self:start_coroutine(do_double, self)
end

local function do_hold(self)
    local poker_data = self.poker_container.config.poker_data_class.new(-1)
    local hand = self.poker_container.hand
    local to_hold = {}
    for _, poker in ipairs(hand) do
        if poker.selected then
            table.insert(to_hold, poker.data.server_value)
        else
            poker:flip(poker_data)
        end
    end
    game.input.wait(0.6, "翻牌动画")
    game.store.ingame.hold(to_hold)
end

local function do_deal(self)
    self:gray_hand(false)
    local poker_data = self.poker_container.config.poker_data_class.new(-1)
    local hand = self.poker_container.hand
    local is_flip = false
    for _, poker in ipairs(hand) do 
        if poker.data.client_value ~= -1 then
            poker:flip(poker_data)
            is_flip = true
        end   
    end
    if is_flip then
        game.input.wait(0.6, "发牌动画")
    end
    game.store.ingame.deal()
end

function M:on_deal()
    local player = game.kbe.player()
    if not player then
        return
    end
    if player.chip < app.store.bet_amounts.state.amount then
        game.msgbox.show({
            content = game.i18n.text("no money"),
            on_confirm = function() self:on_exit_game() end,
        })
        return
    end
    if game.store.ingame.state.phase == consts.PHASE_DEAL then
        self:start_coroutine(do_hold, self)
    else
        self:start_coroutine(do_deal, self)
    end
end

function M:on_pick(poker)
    local hand = self.poker_container.hand
    local selected_idx = -1
    for index, p in ipairs(hand) do
        if poker == p then
            selected_idx = index-1
            break
        end
    end

    if selected_idx < 0 then
        print("还没选择")
        return
    end

    game.kbe.player():pick(selected_idx)
    self:ope_valid(false)
end

function M:on_exit_game()
    game.store.ingame.exit_game()
    game.game_scene.leave()
end

function M:ope_valid(b)
    if not b then
        local hand = self.poker_container.hand
        for index, poker in ipairs(hand) do
            poker:forbid()
        end
    end

    self.poker_container.config.ope_valid = b
end

function M:tip_hand(rank_class)
    local pokers = {}
    local nums = {}
    for _, poker in ipairs(self.poker_container.hand) do
        if not nums[poker.data.client_value] then
            nums[poker.data.client_value] = {}
        end
        table.insert(nums[poker.data.client_value], poker)
    end

    if rank_class == game.util.consts.RANK_JACKS_PAIR then
        for client_value, t in pairs(nums) do
            if #t == 2 then
                pokers = t
                break
            end
        end
    elseif rank_class == game.util.consts.RANK_TWO_PAIR then
        for client_value, t in pairs(nums) do
            if #t == 2 then
                for _, poker in ipairs(t) do
                    table.insert(pokers, poker)
                end
            end
        end
    elseif rank_class == game.util.consts.RANK_THREE_OF_A_KIND then
        for client_value, t in pairs(nums) do
            if #t == 3 then
                pokers = t
                break
            end
        end
    elseif rank_class == game.util.consts.RANK_STRAIGHT then
        pokers = self.poker_container.hand
    elseif rank_class == game.util.consts.RANK_FLUSH then
        pokers = self.poker_container.hand
    elseif rank_class == game.util.consts.RANK_FULL_HOUSE then
        pokers = self.poker_container.hand
    elseif rank_class == game.util.consts.RANK_FOUR_OF_A_KIND then
        for client_value, t in pairs(nums) do
            if #t == 4 then
                pokers = t
                break
            end
        end
    elseif rank_class == game.util.consts.RANK_STRAIGHT_FLUSH then
        pokers = self.poker_container.hand
    elseif rank_class == game.util.consts.RANK_ROYAL_STRAIGHT_FLUSH then
        pokers = self.poker_container.hand
    end

    for _, poker in ipairs(self.poker_container.hand) do
        for _, selected_poker in ipairs(pokers) do
            if poker == selected_poker then
                poker:select()
                break
            end
        end
    end
end

function M:gray_hand(b)
    for _, poker in ipairs(self.poker_container.hand) do
        poker:gray(b)
    end
end

return M
